package com.njtoyo.taxi.admin.logic.business;


import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.njtoyo.taxi.admin.cache.PrimaryCachePutter;
import com.njtoyo.taxi.admin.library.common.OperationRecordHelper;
import com.njtoyo.taxi.admin.mapper.master.entity.Company;
import com.njtoyo.taxi.admin.mapper.master.entity.Ride;
import com.njtoyo.taxi.admin.mapper.master.entity.SimpleCallRide;
import com.njtoyo.taxi.admin.mapper.master.entity.Taxi;
import com.njtoyo.taxi.admin.mapper.master.enums.RideStateState;
import com.njtoyo.taxi.admin.mapper.master.enums.SimpleCallRideState;
import com.njtoyo.taxi.admin.mapper.master.mapper.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.Arrays;
import java.util.Date;
import java.util.List;

import static java.util.regex.Pattern.matches;


@Service
@Slf4j
public class TaxisLogic {

    @Autowired
    private TaxiMapper taxiMapper;
    @Autowired
    private PrimaryCachePutter primaryCachePutter;
    @Autowired
    private DriverMapper driverMapper;
    @Autowired
    private OperationRecordHelper operationRecordHelper;
    @Autowired
    private CompanyMapper companyMapper;
    @Autowired
    private RideMapper rideMapper;
    @Autowired
    private SimpleCallRideMapper simpleCallRideMapper;

    /**
     * 车辆注册
     */
    public Taxi registerBatch(String plateNumber, String serialNumber, Long companyId) {
        if (ObjectUtils.isEmpty(plateNumber)) {
            throw new RuntimeException("车牌号码不能为空");
        }
        //校验车牌号,发动机号
        String pattern = "[测京津晋冀蒙辽吉黑沪苏浙皖闽赣鲁豫鄂湘粤桂琼渝川贵云藏陕甘青宁新][A-Za-z0-9]+";
        boolean flag = matches(pattern, plateNumber);
        if (!flag) {
            throw new RuntimeException("车牌号码格式错误");
        }
        if (ObjectUtils.isEmpty(serialNumber)) {
            throw new RuntimeException("发动机号不能为空");
        }
        Company company = companyMapper.selectById(companyId);
        if (ObjectUtils.isEmpty(company)) {
            throw new RuntimeException("公司id对应的公司不存在");
        }
        Taxi taxi = new Taxi();
        Integer count = taxiMapper.selectPlateNumber(plateNumber);
        if (count >= 1) {
            throw new RuntimeException("车牌号已经被注册");
        }
        taxi.setCompanyId(companyId);
        taxi.setSerialNumber(serialNumber);
        taxi.setPlateNumber(plateNumber);
        taxiMapper.insert(taxi);
        Long id = taxi.getId();
        operationRecordHelper.addBusinessLog(String.format("注册了车辆 [%d] 的车牌号为 %s 的信息", id, plateNumber));
        return taxi;
    }


    /**
     * 车辆报废
     */
    public Taxi scrapBatch(Long id, Boolean isScrapped) {
        Taxi taxi = taxiMapper.selectById(id);
        if (ObjectUtils.isEmpty(taxi)) {
            throw new RuntimeException("车辆不存在");
        }
        new LambdaUpdateChainWrapper<>(taxiMapper)
                .eq(Taxi::getId, id)
                .set(Taxi::getIsScrapped, isScrapped)
                .set(Taxi::getUpdatedAt, new Date())
                .update();
        List<Long> longs = driverMapper.selectDriverByIds(id);
        //清除掉绑定该车辆的司机缓存
        for (Long l : longs) {
            primaryCachePutter.deleteDriverCacheById(l);
        }
        if (isScrapped) {
            operationRecordHelper.addBusinessLog(String.format("报废了车辆 [%d] 的信息", id));
        } else {
            operationRecordHelper.addBusinessLog(String.format("重新启用了车辆 [%d] 的信息", id));
        }
        return taxi;
    }

    // 根据 taxiId，将 is_available 设置为true
    public boolean updateIsAvailableTrue(Long taxiId) {
        return new LambdaUpdateChainWrapper<>(taxiMapper)
                .eq(Taxi::getId, taxiId)
                .set(Taxi::getIsAvailable, true)
                .set(Taxi::getUpdatedAt, new Date())
                .update();
    }


    /**
     * 车辆是否可接单
     *
     * @param taxiId
     * @return
     */
    public boolean taxiIsCanReceive(Long taxiId) {
        List<Ride> rides = rideMapper.selectList(Wrappers.<Ride>lambdaQuery()
                .eq(Ride::getTaxiId, taxiId)
                .in(Ride::getState, Arrays.asList(RideStateState.waiting, RideStateState.contracted, RideStateState.pickuping, RideStateState.started, RideStateState.inarea)));
        if (CollUtil.isNotEmpty(rides)) {
            return false;
        }
        List<SimpleCallRide> simpleCallRides = simpleCallRideMapper.selectList(Wrappers.<SimpleCallRide>lambdaQuery()
                .eq(SimpleCallRide::getTaxiId, taxiId)
                .in(SimpleCallRide::getState, Arrays.asList(SimpleCallRideState.pickUp, SimpleCallRideState.inArea, SimpleCallRideState.start)));

        if (CollUtil.isNotEmpty(simpleCallRides)) {
            return false;
        }
        return true;
    }
}

